<template>
  <div id="predict">
    <div class="button-group">
      <el-select placeholder="选择训练策略" class="input" v-model="form.stragyId">
        <el-option v-for="dict in stragyDict.value" :key="dict.value" :label="dict.label" :value="dict.value" />
      </el-select>
      <el-select placeholder="选择预测数据集" class="input" v-model="form.testId">
        <el-option v-for="dict in lscDataList.value" :key="dict.value" :label="dict.label" :value="dict.value" />
      </el-select>
      <el-input placeholder="选择预测周期" class="input" v-model="form.predCircle"></el-input>
      <el-button type="primary" class="button" @click="submitForm">开始预测</el-button>
      <el-button type="danger" class="button" @click="stopPred">停止预测</el-button>
      <el-button type="warning" class="button" @click="exportData">导出结果</el-button>
    </div>
    <div class="pre-area">
      <div>
        <div style="width: 700px; height: 450px;" v-if="tableShow">
          <bar-charts :line-data="lineData" :bar-data="barData" :x-axis="xAxis" title="预测结果" />
        </div>
        <div v-else style="width: 700px; height: 450px;padding: 20px">
          <div class="background">
            <div style="position: relative;top: 190px;font-size: 30px;color: white;font-weight: bold">{{showTip}}</div>
          </div>
        </div>
      </div>
      <div class="chart">
        <div style="font-size: 18px;font-weight: bold;color: rgb(70, 70, 70)">历史预测记录</div>
        <el-table v-loading="loading" :data="lscList" @selection-change="handleSelectionChange" style="margin-top: 20px">
          <el-table-column label="训练策略" align="center" prop="stragyId">
            <template v-slot="scope">
              {{ stragyDict.value.find(item => item.value == scope.row.stragyId)?.label || '处理情况未知' }}
            </template>
          </el-table-column>
          <el-table-column label="测试集" align="center" prop="testId" width="130">
            <template v-slot="scope">
              {{ lscDataList.value.find(item => item.value == scope.row.testId)?.label || '处理情况未知' }}
            </template>
          </el-table-column>
          <el-table-column label="预测周期" align="center" prop="predCircle" width="80" />
          <el-table-column label="预测时间" align="center" prop="historyPred" width="100">
            <template v-slot="scope">
              {{ scope.row.historyPred.slice(10) }}
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
            <template #default="scope">
              <el-tooltip content="导出" placement="top">
                <el-button link type="primary" icon="Download" @click="exportHistoryData(scope.row.testId)" v-hasPermi="['system:lsc:edit']">导出</el-button>
              </el-tooltip>
              <el-tooltip content="删除" placement="top">
                <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:lsc:remove']">删除</el-button>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          v-show="total>0"
          :total="total"
          v-model:page="queryParams.pageNum"
          v-model:limit="queryParams.pageSize"
          @pagination="getHistoryList"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
/* ts */
import { listStragyLsc } from "@/api/lsc/strategy";
import { getLsc, listLsc } from "@/api/lsc/dataset";
import { addPreLsc, delPreLsc, listPreLsc, updatePreLsc } from "@/api/lsc/predict";
import { LscPreForm, LscPreQuery, PreLscVO } from "@/api/lsc/predict/types";
import axios from 'axios';
import { globalHeaders } from "@/utils/request";
import { blobValidate } from "@/utils/ruoyi";
import * as XLSX from "_xlsx@0.18.5@xlsx";
import FileSaver from 'file-saver';
import { format } from 'date-fns';


// eslint-disable-next-line @typescript-eslint/no-unused-vars
const queryFormRef = ref<ElFormInstance>();
interface DataDict {
  value: { label: string; value: string | number }[];
}

interface countDict {
  value: { value: string | number; count: string | number }[];
}
const historyDict = reactive<countDict>({
  value: []
})
const stragyDict = reactive<DataDict>({
  value: []
});
const lscDataList = reactive<DataDict>({
  value: []
});
const lscPreDict = reactive<DataDict>({
  value: []
});
const lineData = ref([] as any[])
const ids = ref<Array<string | number>>([]);
const barData = ref([] as any[])
const xAxis = ref([] as any[])
const showTip = ref("无预测数据")
const baseURL = import.meta.env.VITE_APP_BASE_API;
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const lscList = ref<PreLscVO[]>([]);
const total = ref(0);
const loading = ref(true);
const single = ref(true);
const multiple = ref(true);
const initFormData: LscPreForm = {
  id: undefined,
  stragyId: undefined,
  testId: undefined,
  predCircle: undefined,
  historyPred: undefined
}
const data = reactive<PageData<LscPreForm, LscPreQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    stragyId: undefined,
    testId: undefined,
    predCircle: undefined,
    historyPred: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "主键不能为空", trigger: "blur" }
    ],
    stragyId: [
      { required: true, message: "训练策略不能为空", trigger: "blur" }
    ],
    testId: [
      { required: true, message: "测试集不能为空", trigger: "blur" }
    ],
    predCircle: [
      { required: true, message: "预测周期不能为空", trigger: "blur" }
    ],
    historyPred: [
      { required: true, message: "历史预测不能为空", trigger: "blur" }
    ]
  }
});
const { queryParams, form, rules } = toRefs(data);
const tableShow = ref(false)
const predDataId = ref("")
onMounted(() => {
  init()
})
const init = async () => {
  loading.value = false
  const res = await listStragyLsc(Object.assign({ trainStatus: 1 }));
  res.rows.forEach(item => {
    stragyDict.value.push({
      label: String(item.stragyName),
      value: String(item.id)
    })
  });
  await getDatasetList();
  await getList()
  await getHistoryList()
}
const getHistoryList = async () => {
  loading.value = true;
  const res = await listPreLsc(queryParams.value);
  lscList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** 多选框选中数据 */
const handleSelectionChange = (selection: PreLscVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
const stopPred = () => {
  tableShow.value = false
  showTip.value = "无预测数据"
}
const exportHistoryData = async (rowId: string) => {
  const response = await getLsc(rowId);
  const url = baseURL + '/resource/oss/download/' + String(response.data);
  const res = await axios({
    method: 'get',
    url: url,
    responseType: 'blob',
    headers: globalHeaders()
  });
  const blob = new Blob([res.data], { type: 'application/octet-stream' });
  console.log('blob', blob)
  FileSaver.saveAs(blob, decodeURIComponent(res.headers['download-filename'] as string));
}
const exportData = async () => {
  if (predDataId.value == ""  || predDataId.value == undefined) {
    proxy?.$modal.msgWarning("请先预测数据");
    return
  }
  const url = baseURL + '/resource/oss/download/' + predDataId.value;
  const res = await axios({
    method: 'get',
    url: url,
    responseType: 'blob',
    headers: globalHeaders()
  });
  const blob = new Blob([res.data], { type: 'application/octet-stream' });
  console.log('blob', blob)
  FileSaver.saveAs(blob, decodeURIComponent(res.headers['download-filename'] as string));
}
/** 删除按钮操作 */
const handleDelete = async (row?: PreLscVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除该记录').finally(() => loading.value = false);
  await delPreLsc(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getHistoryList();
}
const getList = async () => {
  const res = await listPreLsc(queryParams.value);
  res.rows.forEach(row => {
    lscPreDict.value.push({
      label: String(row.testId),
      value: row.id
    });
  })
  console.log("preDict", lscPreDict.value)
}
const getDatasetList = async () => {
  const res = await listLsc(Object.assign({ dataType: 2, status: 1 }));
  res.rows.forEach(data => {
    lscDataList.value.push({
      label: data.dataName,
      value: data.id,
    })
  })
}
const submitForm = async () => {
  historyDict.value.push({value: 0, count: 1})
  form.value.historyPred = format(new Date(), 'yyyy-MM-dd HH:mm:ss')
  if (form.value.id) {
    await updatePreLsc(form.value);
  } else {
    await addPreLsc(form.value);
  }
  showTip.value = "无预测数据"
  showTip.value = "预测中..."
  await startTrain(String(form.value.testId))
  proxy?.$modal.msgSuccess("修改成功");
  loading.value = false
  await getHistoryList()
}
const startTrain = async (predId: string | number) => {
  showTip.value = "开始预测..."
  const response = await getLsc(predId);
  predDataId.value = response.data.dataFile;
  await getData(String(response.data.dataFile));
}
const getData = async (ossId: string) => {
  const url = baseURL + '/resource/oss/download/' + ossId;
  const res = await axios({
    method: 'get',
    url: url,
    responseType: 'blob',
    headers: globalHeaders()
  });
  const isBlob = blobValidate(res.data);
  if (isBlob) {
    const blob = new Blob([res.data], { type: 'application/octet-stream' });
    // FileSaver.saveAs(blob, decodeURIComponent(res.headers['download-filename'] as string));
    await readExcel(blob)
  }
}
const readExcel = async (file: Blob) => {
  // 确保有文件可读
  if (!file) {
    alert('请先选择一个Excel文件');
    return;
  }
  const reader = new FileReader();
  // 读取文件完成后的回调
  reader.onload = (event) => {
    const data = new Uint8Array((event.target as any).result);
    // 使用 xlsx 读取数据
    const workbook = XLSX.read(data, { type: 'array' });
    console.log("data", workbook)
    // 获取第一个工作表
    const firstSheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[firstSheetName];
    const jsonData = ref([] as any[])
    // 将 Excel 数据转换为 JSON 对象
    jsonData.value = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
    console.log("reader", jsonData.value)
    xAxis.value = Array.from({ length: Number(form.value.predCircle)}, (_, i) => String(i + 1));
    lineData.value = jsonData.value.slice(1).filter((row: string | any[]) => row.length >= 1).map((row: any[]) => row[0]);;
    barData.value = jsonData.value.slice(1).filter((row: string | any[]) => row.length >= 1).map((row: any[]) => row[0]);;
    tableShow.value = true;
  };
  // 读取文件为 ArrayBuffer
  reader.readAsArrayBuffer(file);
};
</script>

<style scoped lang="scss">
/* 样式 */
#predict {
  padding: 10px;
  background-color:  #1ab394;
}
.button-group {
  padding: 10px;
  background-color: #FFFFFF;
  border-radius: 3px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease;
}
.background {
  background-color: #707070;
  width: 100%;
  height: 100%;
  text-align: center;
}
.input {
  width: 200px;
  margin-left: 10px;
}
.button {
  margin-left: 10px;
}
.pre-area {
  display: flex;
  padding: 20px;
  margin-top: 20px;
  background-color: #FFFFFF;
  border-radius: 3px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease;
  overflow: hidden;
}
.chart {
  position: relative;
  padding: 10px;
  width: 800px;
}
</style>
